package com.vhall.component.service.record.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.vhall.component.dao.account.AccountMapper;
import com.vhall.component.dao.audit.AuditRecordMapper;
import com.vhall.component.dao.record.RecordChapterMapper;
import com.vhall.component.dao.record.RecordMapper;
import com.vhall.component.dao.room.AnchorRoomRelationMapper;
import com.vhall.component.dao.room.RoomMapper;
import com.vhall.component.dao.room.RoomReservationThirdMapper;
import com.vhall.component.entity.account.AccountEntity;
import com.vhall.component.entity.audit.dto.CreateAuditRecordDTO;
import com.vhall.component.entity.audit.entity.AuditRecordEntity;
import com.vhall.component.entity.audit.vo.AuditRecordResponseVO;
import com.vhall.component.entity.paas.AddKeyFrameDescReqVO;
import com.vhall.component.entity.record.RecordChapterEntity;
import com.vhall.component.entity.record.RecordEntity;
import com.vhall.component.entity.record.RecordEntityDTO;
import com.vhall.component.entity.record.vo.*;
import com.vhall.component.entity.room.dto.RoomsEntityDTO;
import com.vhall.component.entity.room.entity.AnchorRoomRelationEntity;
import com.vhall.component.entity.room.entity.RoomPushMsgThirdEntity;
import com.vhall.component.entity.room.entity.RoomReservationThirdEntity;
import com.vhall.component.entity.room.entity.RoomsEntity;
import com.vhall.component.entity.room.enums.*;
import com.vhall.component.entity.room.vo.RoomConsoleListRespVO;
import com.vhall.component.entity.room.vo.RoomConsoleListVO;
import com.vhall.component.entity.room.vo.RoomsEntityVO;
import com.vhall.component.entity.subject.enums.StatusEnum;
import com.vhall.component.framework.common.exception.BusinessException;
import com.vhall.component.framework.common.utils.CollectionUtils;
import com.vhall.component.framework.common.utils.DateTimeUtils;
import com.vhall.component.plugin.common.annotation.TokenAuth;
import com.vhall.component.plugin.common.constant.ConstStr;
import com.vhall.component.plugin.common.constant.HttpConstant;
import com.vhall.component.plugin.common.constant.PaasCommonConstant;
import com.vhall.component.plugin.common.constant.RedisKey;
import com.vhall.component.plugin.common.exception.BizErrorCode;
import com.vhall.component.plugin.common.support.Token;
import com.vhall.component.plugin.common.support.TokenThreadLocal;
import com.vhall.component.plugin.common.utils.BeanCopyUtil;
import com.vhall.component.plugin.common.utils.DateUtils;
import com.vhall.component.plugin.core.service.PaasService;
import com.vhall.component.service.audit.AuditRecordService;
import com.vhall.component.service.record.RecordChapterService;
import com.vhall.component.service.record.RecordService;
import com.vhall.component.service.record.constant.RecordConstant;
import com.vhall.component.service.room.RoomInnerService;
import com.vhall.component.service.room.RoomPushMsgThirdService;
import com.vhall.component.service.room.concant.RoomConstant;
import com.vhall.component.service.room.impl.RoomBaseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Preconditions;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.vhall.component.plugin.common.constant.RedisKey.ROOM_DEFAULT_RECORD;

/**
 * record 测试版迁移
 *
 * @author dongsong
 */
@Slf4j
@Service
public class RecordServiceImpl extends RoomBaseService implements RecordService {

    private static final String PAGE_ESCAPE = "\\/?page=";
    private static final String TRANSCODE_STATUS = "transcode_status";
    private static final String DURATION = "duration";
    private static final String STORAGE = "storage";
    private static final String STATUS = "status";
    private static final String LIMIT_0_1 = "limit 0, 1";
    private static final String DOWN_URL = "down_url";


    /**
     * 0:初始化； 1:已发布 ； 2:回放生成成功；3:回放生成失败；
     * 4:审核中；5:审核成功； 6: 审核失败；7: 转码中；8:转码失败；9:转码部分成功；
     */
    private final List<Integer> vodSuccessStatus = Arrays.asList(1, 2, 5);

    private final List<Integer> vodErrorStatus = Arrays.asList(3, 6);

    @Value("${paas.apps.lite.appId}")
    public String appId;


    @Autowired
    private PaasService paasService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Autowired
    private RecordMapper recordMapper;

    @Autowired
    private RoomInnerService roomInnerService;

    @Autowired
    public RoomMapper roomMapper;

    @Resource
    private AuditRecordService auditRecordService;

    @Resource
    private AnchorRoomRelationMapper anchorRoomRelationMapper;

    @Resource
    private AccountMapper accountMapper;
    @Resource
    private AuditRecordMapper auditRecordMapper;

    @Autowired
    private RoomReservationThirdMapper roomReservationThirdMapper;

    @Resource
    private RecordChapterMapper recordChapterMapper;
    @Resource
    private RecordChapterService recordChapterService;
    @Resource
    private RoomPushMsgThirdService roomPushMsgThirdService;

    /**
     * 查询回放列表
     */
    @Override
    public GetRecordListRspVo getRecordList(GetRecordListReqVo reqVo) {

        GetRecordListRspVo result = new GetRecordListRspVo();
        int currPage = reqVo.getPage() == null ? 1 : reqVo.getPage();
        int pageSize = reqVo.getPageSize() == null ? 10 : reqVo.getPageSize();
        //查询房间信息
        LambdaQueryWrapper<RoomsEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(RoomsEntity::getRoomId, reqVo.getRoomId());
        queryWrapper.last(" limit 1");
        RoomsEntity roomsEntity = roomMapper.selectOne(queryWrapper);
        if (roomsEntity == null) {
            log.error("房间id：{}不存在", reqVo.getRoomId());
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }
        //调用PAAS接口同步回放信息
        syncRecords(roomsEntity);

        // 自动创建默认回放视频
        autoGenDefaultRecord(roomsEntity);

        //房间的默认回放ID
        String recordId = roomsEntity.getRecordId();
        reqVo.setIlId(roomsEntity.getIlId());
        //查询回放列表
        Page<RecordEntity> page = new Page<>(currPage, pageSize);
        IPage<RecordEntity> recordEntityIPage = recordMapper.selectPageList(page, reqVo);


        List<RecordRsp> recordRspList = new ArrayList<>();
        recordEntityIPage.getRecords().forEach(recordEntity -> recordRspList.add(convertToRecordRspVo(recordEntity
                , recordId
                ,roomsEntity.getLiveContentType().equals(LiveContentTypeEnum.TYPE_3.getValue()))));
        result.setRecordRspList(recordRspList);
        result.setCurrentPage(currPage);
        result.setLastPage((int) recordEntityIPage.getPages());
        result.setPerPage(String.valueOf(pageSize));
        result.setTotal((int) recordEntityIPage.getTotal());
        result.setFrom((currPage - 1) * pageSize + 1);
        result.setTo(Math.min(currPage * pageSize, (int) recordEntityIPage.getTotal()));

        int lastPage = (int) recordEntityIPage.getPages();
        result.setFirstPageUrl("\\/?page=1");
        result.setLastPageUrl(PAGE_ESCAPE + (int) recordEntityIPage.getPages());
        String prevPage = currPage == 1 ? null : PAGE_ESCAPE + (currPage - 1);
        String nextPage = currPage == lastPage ? null : PAGE_ESCAPE + (currPage + 1);
        result.setPrevPageUrl(prevPage);
        result.setNextPageUrl(nextPage);
        result.setPath("\\/");
        return result;
    }

    private void autoGenDefaultRecord(RoomsEntity roomsEntityDto) {

        String key = ROOM_DEFAULT_RECORD + roomsEntityDto.getRoomId();
        String o = redisTemplate.opsForValue().get(key);
        if (StringUtils.isNotBlank(o) && "0".equals(o)) {
            // 查询回放信息
            LambdaQueryWrapper<RecordEntity> where = Wrappers.lambdaQuery();
            where.eq(RecordEntity::getRoomId, roomsEntityDto.getRoomId());
            where.eq(RecordEntity::getSource, 0);
            where.eq(RecordEntity::getStatus, 0);
            where.orderByDesc(RecordEntity::getId);
            List<RecordEntity> recordEntities = recordMapper.selectList(where);
            if (org.apache.commons.collections.CollectionUtils.isNotEmpty(recordEntities)) {
                RecordEntity recordEntity = recordEntities.get(0);

                if (StringUtils.isBlank(roomsEntityDto.getRecordId()) || !roomsEntityDto.getRecordId().equals(recordEntity.getVodId())) {

                    roomsEntityDto.setRecordId(recordEntity.getVodId());
//                    int rowEffect = roomInnerService.updateByIl(roomsEntityDto);
                    redisTemplate.opsForValue().set(key, "1");
                    log.info(MessageFormat.format("当前房间：【{0}】，完成设置默认回放设置", roomsEntityDto.getRoomId()));
                }

            }
        }

    }

    /**
     * 同步回放信息
     */
    private void syncRecords(RoomsEntity roomsEntity) {
        Map<String, Object> param = new HashMap<>(16);
        param.put("room_id", roomsEntity.getRoomId());

        param.put("endtime", LocalDateTimeUtil.formatNormal(LocalDateTime.now()));

        LocalDateTime lastY = LocalDateTime.now().minusYears(1);
        String startT = LocalDateTimeUtil.formatNormal(LocalDateTimeUtil.beginOfDay(lastY));
        param.put("starttime", startT);

        int pageNum = 0;
        param.put(PaasCommonConstant.PAGE_SIZE_KEY, 100);
        param.put("source", "");
        param.put(PaasCommonConstant.STATUS, "");
        param.put("sortby", "created_at:desc");
        JSONArray finalArray = new JSONArray();
        while (true) {
            param.put("page_num", pageNum);
            JSONObject returnObj = paasService.getRecordList(param);
            JSONArray array = returnObj.getJSONArray("list");
            finalArray.addAll(array);
            int totalPage = returnObj.getInteger("page_all");
            if (pageNum >= totalPage) {
                break;
            }
            pageNum++;
        }
        if (CollectionUtils.isNotEmpty(finalArray)) {
            for (Object o : finalArray) {
                JSONObject jsonObject = (JSONObject) o;
                String vodId = jsonObject.getString(PaasCommonConstant.VOD_ID_KEY);
                int count = recordMapper.selectCount(Wrappers.<RecordEntity>lambdaQuery()
//                        .eq(RecordEntity::getAccountId, roomsEntity.getAccountId())
                        .eq(RecordEntity::getIlId, roomsEntity.getIlId())
                        .eq(RecordEntity::getVodId, vodId));
                if (count <= 0) {
                    //创建回放
                    RecordEntity recordEntity = new RecordEntity();
                    LocalDateTime now = LocalDateTime.now();
                    recordEntity.setIlId(roomsEntity.getIlId());
                    recordEntity.setRoomId(roomsEntity.getRoomId());
                    recordEntity.setAccountId(roomsEntity.getAccountId());
                    recordEntity.setVodId(vodId);
                    recordEntity.setName(jsonObject.getString("name"));
                    recordEntity.setTranscodeStatus(jsonObject.getInteger(TRANSCODE_STATUS));
                    recordEntity.setDuration(jsonObject.getInteger(DURATION));
                    recordEntity.setStorage(jsonObject.getInteger(STORAGE));
                    recordEntity.setSource(jsonObject.getInteger("source"));
                    LocalDateTime ct = LocalDateTime.parse(jsonObject.getString("created_at"), DatePattern.NORM_DATETIME_FORMATTER);
                    recordEntity.setCreatedTime(ct);
                    recordEntity.setCreatedAt(now);
                    recordEntity.setUpdatedAt(now);
                    recordMapper.insert(recordEntity);
                } else {

                    LambdaUpdateWrapper<RecordEntity> update = Wrappers.lambdaUpdate();
                    update.set(jsonObject.getInteger(STORAGE) != null, RecordEntity::getStorage, jsonObject.getInteger(STORAGE)).set(jsonObject.getInteger(DURATION) != null, RecordEntity::getDuration, jsonObject.getInteger(DURATION)).set(RecordEntity::getUpdatedAt, LocalDateTime.now()).eq(RecordEntity::getIlId, roomsEntity.getIlId()).eq(RecordEntity::getVodId, vodId);
                    log.info(MessageFormat.format("更新回放:[{0}]", update.toString()));
                    recordMapper.update(null, update);

                }
            }
        }
    }

    /**
     * 设置默认回放
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setDefaultRecord(SetDefaultRecordReqVo reqVO) {

        RoomsEntityDTO roomsEntity = Optional.ofNullable(roomInnerService.getRoomInfo(reqVO.getRoomId())).orElseThrow(()->new BusinessException(BizErrorCode.EMPTY_ROOM));
        Integer liveContentType = roomsEntity.getLiveContentType();
        //查询回放信息
        RecordEntity recordEntity = recordMapper.selectOne(Wrappers.<RecordEntity>lambdaQuery()
                .eq(RecordEntity::getRoomId, reqVO.getRoomId())
                .eq(RecordEntity::getVodId, reqVO.getRecordId()).last(LIMIT_0_1));
        if (recordEntity == null) {
            log.error("房间id：{}，回放id：{}的回放信息不存在", reqVO.getRoomId(), reqVO.getRecordId());
            throw new BusinessException(BizErrorCode.EMPTY_RECORD);
        }

        // 基本校验
        setDefaultRecordBasicValidate(liveContentType, recordEntity,roomsEntity,reqVO);

        int count = roomInnerService.getCountByIlidAndRecordId(recordEntity.getIlId().toString(), reqVO.getRecordId());
        //默认回放ID，空为取消默认回放
        String recordId = count > 0 ? "" : reqVO.getRecordId();

        if (roomsEntity.getLiveRormal() == 0) {
            // 测试房间/点播房间 直接通过 无需审核
            jumpTestRoom(roomsEntity, recordEntity);
            return;
        }
        if (roomsEntity.getLiveType() == 2 && recordEntity.getSource() != 1) {
//            点播房间 直接通过 无需审核
            jumpVodRoom(roomsEntity, recordEntity);
            return;
        }

        // 更新房间审核信息
        updateRoomPlayInfo(reqVO, roomsEntity, recordEntity, recordId);

        // 房间的
        if (recordEntity.getAuditStatus() == 9) {
            // 设置默认回放，会将视频从待送审变更为待审核状态
            recordEntity.setAuditStatus(0);
            recordMapper.updateById(recordEntity);
            createSendRecordAuditMessage(roomsEntity,recordEntity);
        }

    }

    /**
     * 创建发送回放审核通知消息记录
     * - 回放审核时,将消息发送给所有回放相关的主播
     * @param roomsEntityDTO
     * @param recordEntity
     */
    private void createSendRecordAuditMessage(RoomsEntityDTO roomsEntityDTO, RecordEntity recordEntity) {
        Optional.ofNullable(roomsEntityDTO).orElseThrow(()->new BusinessException(BizErrorCode.EMPTY_ROOM));

        Integer ilId = roomsEntityDTO.getIlId();
        RoomsEntity roomsEntity = new RoomsEntity();
        BeanUtils.copyProperties(roomsEntityDTO,roomsEntity);
        List<AnchorRoomRelationEntity> anchorRoomRelationEntities = getRoomAnchorRoomRelationList(ilId);
        if (CollUtil.isNotEmpty(anchorRoomRelationEntities)) {
            List<String> userCodeList = anchorRoomRelationEntities.stream().map(AnchorRoomRelationEntity::getUserCode).distinct().collect(Collectors.toList());
            List<RoomPushMsgThirdEntity> roomPushMsgThirdEntityList = new ArrayList<>();
            for (String userCode : userCodeList) {
                RoomPushMsgThirdEntity data = buildRoomPushMsgThirdEntity(roomsEntity, recordEntity, RoomPushMsgTypeEnum.FIRST_TRIAL_NOTIFICATION, userCode);
                roomPushMsgThirdEntityList.add(data);
            }
            if (CollUtil.isNotEmpty(roomPushMsgThirdEntityList)) {
                roomPushMsgThirdService.saveBatch(roomPushMsgThirdEntityList);
            }
        }

    }

    /**
     * 构建发送房间审核消息通知对象
     * @param roomsEntity 房间对象
     * @param recordEntity 回放对象
     * @param msgType 通知类型
     * @param userCode 接受消息用户编号
     * @return
     */
    @NotNull
    private RoomPushMsgThirdEntity buildRoomPushMsgThirdEntity(RoomsEntity roomsEntity, RecordEntity recordEntity, RoomPushMsgTypeEnum msgType , String userCode) {
        RoomPushMsgThirdEntity data = new RoomPushMsgThirdEntity();
        data.setIlId(roomsEntity.getIlId());
        data.setRoomId(roomsEntity.getRoomId());
        data.setRoomStartTime(roomsEntity.getStartTime());
        data.setSubject(roomsEntity.getSubject());

        data.setMsgType(msgType.getValue());
        data.setAuditNotifyUserCode(userCode);

        data.setPushMessageStatus(StatusEnum.CLOSE.getValue());
        data.setPushEmailStatus(StatusEnum.CLOSE.getValue());
        if (Objects.nonNull(recordEntity)) {
            data.setRemark("提交审核的回放编号为:"+ recordEntity.getVodId());
        }
        LocalDateTime now = LocalDateTime.now();
        data.setCreateTime(now);
        data.setUpdateTime(now);
        return data;
    }

    /**
     * 获取直播间对应的主播信息
     * @param ilId
     * @return
     */
    private List<AnchorRoomRelationEntity> getRoomAnchorRoomRelationList(Integer ilId) {
        LambdaQueryWrapper<AnchorRoomRelationEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(AnchorRoomRelationEntity::getIlId,ilId)
                .isNull(AnchorRoomRelationEntity::getDeletedAt);
        List<AnchorRoomRelationEntity> anchorRoomRelationEntities = anchorRoomRelationMapper.selectList(queryWrapper);
        return anchorRoomRelationEntities;
    }

    private void updateRoomPlayInfo(SetDefaultRecordReqVo reqVO, RoomsEntityDTO roomsEntity, RecordEntity recordEntity, String recordId) {
        Integer playbackStatus;
        String playbackNote="";

        Integer playbackStatusSecond=RoomAuditStatusEnum.CHECK_PENDING.getAuditStatus();
        String playbackNoteSecond="";
        if (recordEntity.getAuditStatus() == 9 || recordEntity.getAuditStatus() == 0) {
            playbackStatus = RoomAuditStatusEnum.CHECK_PENDING.getAuditStatus();
        } else {
            playbackStatus = recordEntity.getAuditStatus();
            // 获取审核记录表详情
            AuditRecordEntity recordEntitie = auditRecordMapper.selectListByRounds("record"
                    , recordEntity.getId().toString()
                    , 1);
            if (recordEntitie != null) {
                playbackNote = recordEntitie.getAuditComments();
            }

            // 获取审核记录表详情
            AuditRecordEntity recordEntitie2 = auditRecordMapper.selectListByRounds("record"
                    , recordEntity.getId().toString()
                    , 2);
            if (recordEntitie2 != null) {
                playbackStatusSecond = recordEntitie2.getAuditStatus();
                playbackNoteSecond = recordEntitie2.getAuditComments();
            }
        }
        String complianceAuditorsCode = reqVO.getComplianceAuditorsCode();
        LambdaUpdateWrapper<RoomsEntity> queryWrapper = Wrappers.lambdaUpdate();
        queryWrapper.eq(RoomsEntity::getIlId, roomsEntity.getIlId());
        queryWrapper.set(RoomsEntity::getRecordId, recordId);
        queryWrapper.set(StrUtil.isNotBlank(complianceAuditorsCode),RoomsEntity::getComplianceAuditorsCode, complianceAuditorsCode);
        queryWrapper.set(RoomsEntity::getPlaybackStatus, playbackStatus);
        queryWrapper.set(RoomsEntity::getPlaybackNote, playbackNote);
        queryWrapper.set(RoomsEntity::getPlaybackStatusSecond, playbackStatusSecond);
        queryWrapper.set(RoomsEntity::getPlaybackNoteSecond, playbackNoteSecond);
        int rowEffect = roomMapper.update(null, queryWrapper);
        if (rowEffect == 0) {
            log.error("房间id：{}的回放信息不存在", reqVO.getRoomId());
            throw new BusinessException(BizErrorCode.COMP_RECORD_UPDATE_FAILED);
        }

        redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + roomsEntity.getRoomId());
        redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + roomsEntity.getIlId());
    }

    private void jumpVodRoom(RoomsEntityDTO roomsEntity, RecordEntity recordEntity) {
        roomsEntity.setRecordId(recordEntity.getVodId());
        roomsEntity.setPlaybackStatus(1);
        roomInnerService.updateByIl(roomsEntity);
        recordEntity.setAuditStatus(1);
        recordMapper.updateById(recordEntity);

        AuditRecordEntity auditRecordEntity = new AuditRecordEntity();
        auditRecordEntity.setAuditTableRecordId(recordEntity.getId().toString());
        auditRecordEntity.setAuditComments("系统自动审核通过");
        auditRecordEntity.setAuditStatus(1);
        auditRecordEntity.setAuditTable("record");
        LocalDateTime now = LocalDateTime.now();
        auditRecordEntity.setCreatedAt(now);
        auditRecordEntity.setUpdatedAt(now);
        auditRecordEntity.setAccountId(0);
        auditRecordEntity.setUpdateBy(0);
        auditRecordMapper.insert(auditRecordEntity);
    }

    private void jumpTestRoom(RoomsEntityDTO roomsEntity, RecordEntity recordEntity) {
        roomsEntity.setRecordId(recordEntity.getVodId());
        roomsEntity.setPlaybackStatus(1);
        roomInnerService.updateByIl(roomsEntity);
        recordEntity.setAuditStatus(1);
        recordMapper.updateById(recordEntity);
    }

    private void setDefaultRecordBasicValidate(Integer liveContentType, RecordEntity recordEntity, RoomsEntityDTO roomsEntity, SetDefaultRecordReqVo reqVO) {
        if (!recordEntity.getAuditStatus().equals(RoomAuditStatusEnum.SUBMIT_FOR_APPROVAL.getAuditStatus())
                && !recordEntity.getAuditStatus().equals(RoomAuditStatusEnum.CHECK_PENDING.getAuditStatus())) {
            if (liveContentType.equals(LiveContentTypeEnum.TYPE_3.getValue())) {
                if (!Objects.equals(recordEntity.getAuditStatusSecond(), RoomAuditStatusEnum.SUBMIT_FOR_APPROVAL.getAuditStatus())
                        && !Objects.equals(recordEntity.getAuditStatusSecond(), RoomAuditStatusEnum.CHECK_PENDING.getAuditStatus())
                ) {
                    //当前直播是产品类，那么二审必须通过
                    Preconditions.checkArgument(recordEntity.getAuditStatusSecond().equals(RoomAuditStatusEnum.APPROVED.getAuditStatus())
                            , "该视频审核未通过,不能设置为默认回放");
                }

            } else {
                //如果不是产品类，一审必须通过
                Preconditions.checkArgument(recordEntity.getAuditStatus().equals(RoomAuditStatusEnum.APPROVED.getAuditStatus())
                        , "该视频审核未通过,不能设置为默认回放");
            }
        }
//        产品类型
        if (liveContentType.equals(LiveContentTypeEnum.TYPE_3.getValue())
                && Objects.equals(roomsEntity.getLiveRormal(), LiveRormalEnum.OFFICIAL_LIVE.getValue())
        ) {
            Preconditions.checkArgument(StrUtil.isNotBlank(reqVO.getComplianceAuditorsCode())
                    , "请选择合规审核人员");
        }
    }

    @Override
    public void cancelDefault(String roomId) {

        RoomsEntityDTO roomsEntity = roomInnerService.getRoomInfo(roomId);
        if (null == roomsEntity) {
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }

        LambdaUpdateWrapper<RoomsEntity> queryWrapper = Wrappers.lambdaUpdate();
        queryWrapper.eq(RoomsEntity::getIlId, roomsEntity.getIlId())
                .set(RoomsEntity::getRecordId, "")
                .set(RoomsEntity::getPlaybackStatus, RoomAuditStatusEnum.SUBMIT_FOR_APPROVAL.getAuditStatus())
                .set(RoomsEntity::getPlaybackNote, null)
                .set(RoomsEntity::getPlaybackStatusSecond, RoomAuditStatusEnum.CHECK_PENDING.getAuditStatus())
                .set(RoomsEntity::getPlaybackNoteSecond, "");// 数据库这里对  `record_id` 的定义是  NOT NULL DEFAULT ''  故而这里不赋值为null

        roomMapper.update(null, queryWrapper);

        redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + roomsEntity.getRoomId());
        redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + roomsEntity.getIlId());

        LambdaQueryWrapper<RoomReservationThirdEntity> roomReservationThirdEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
        roomReservationThirdEntityLambdaQueryWrapper.eq(RoomReservationThirdEntity::getIlId, roomsEntity.getIlId());
        if (roomReservationThirdMapper.selectCount(roomReservationThirdEntityLambdaQueryWrapper) > 0) {
            LambdaUpdateWrapper<RoomReservationThirdEntity> updateWrapper = Wrappers.lambdaUpdate();
            updateWrapper.eq(RoomReservationThirdEntity::getIlId, roomsEntity.getIlId());
            updateWrapper.set(RoomReservationThirdEntity::getHavePlayback, 0);
            roomReservationThirdMapper.update(null, updateWrapper);
        }
    }

    /**
     * 删除回放
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public JSONObject deleteRecord(DeleteRecordReqVo reqVO) {
        String[] arr = reqVO.getRecordId().split(",");
        List<String> list = Arrays.asList(arr);
        //执行删除
        int rowEffect = recordMapper.delete(Wrappers.<RecordEntity>lambdaQuery().in(RecordEntity::getVodId, list));
        if (rowEffect == 0) {
            log.error("删除回放：{}失败", reqVO.getRecordId());
            throw new BusinessException(BizErrorCode.BIZ_DELETE_FAILED);
        }
        RoomsEntityDTO roomsEntity = roomInnerService.getRoomInfo(reqVO.getRoomId());
        if (roomsEntity != null && list.contains(roomsEntity.getRecordId())) {
            roomsEntity.setRecordId("");
            int effect = roomInnerService.updateByIl(roomsEntity);
            if (effect == 0) {
                log.error("删除房间：{}的默认回放，更新房间信息失败", reqVO.getRoomId());
                throw new BusinessException(BizErrorCode.COMP_RECORD_UPDATE_FAILED);
            }
        }
        //调用PAAS服务删除回放
        Map<String, Object> param = new HashMap<>(8);
        param.put(PaasCommonConstant.VOD_ID_KEY, reqVO.getRecordId());
        return paasService.recordDel(param);
    }

    /**
     * 获取回放信息
     */
    @Override
    public GetRecordRspVo getRecord(GetRecordReqVo reqVO) {
        RecordEntity recordEntity = recordMapper.selectOne(Wrappers.<RecordEntity>lambdaQuery()
                .eq(RecordEntity::getRoomId, reqVO.getRoomId())
                .eq(RecordEntity::getVodId, reqVO.getRecordId()).last(LIMIT_0_1));
        if (recordEntity == null) {
            log.error("房间id：{}，回放id：{}的回放信息不存在", reqVO.getRoomId(), reqVO.getRecordId());
            throw new BusinessException(BizErrorCode.EMPTY_RECORD);
        }
        GetRecordRspVo getRecordRspVo = new GetRecordRspVo();
        BeanCopyUtil.copy(recordEntity, getRecordRspVo);


        LocalDateTime createdTime = recordEntity.getCreatedTime();
        LocalDateTime createdAt = recordEntity.getCreatedAt();
        LocalDateTime updatedAt = recordEntity.getUpdatedAt();
        getRecordRspVo.setUpdatedAt(updatedAt.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
        getRecordRspVo.setCreatedAt(createdAt.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
        getRecordRspVo.setCreatedTime(createdTime.format(DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN)));
        getRecordRspVo.setDeletedAt(null);

        return getRecordRspVo;
    }

    /**
     * 获取音视频列表
     */
    @Override
    public GetUploadListRspVo getUploadList(GetUploadListReqVo reqVo, Integer accountId) {

        GetUploadListRspVo getUploadListRspVo = new GetUploadListRspVo();
        int currPage = reqVo.getPageNum() == null ? 1 : reqVo.getPageNum();
        int pageSize = reqVo.getPageSize() == null ? 10 : reqVo.getPageSize();
        List<Integer> accountIdsOfOrg = null;
        Token token = TokenThreadLocal.getToken();
        if (token.getRoleType() == 2) {
            AccountEntity accountEntity = accountMapper.selectById(accountId);
            LambdaQueryWrapper<AccountEntity> accountEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
            accountEntityLambdaQueryWrapper.eq(AccountEntity::getOrgCode, accountEntity.getOrgCode());
            List<AccountEntity> accountEntities = accountMapper.selectList(accountEntityLambdaQueryWrapper);
            accountIdsOfOrg = accountEntities.stream().map(AccountEntity::getAccountId).collect(Collectors.toList());
            reqVo.setAccountId(null);
        }

        Page<RecordEntity> page = new Page<>(currPage, pageSize);
        page = recordMapper.selectPageInfo(page, reqVo, accountIdsOfOrg);
        List<UploadRsp> uploadRspList = new ArrayList<>();

        Map<Integer, String> ilIdMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(page.getRecords())) {
            List<Integer> ilIdList = page.getRecords().stream().map(RecordEntity::getIlId).collect(Collectors.toList());
            List<RoomsEntityDTO> roomInfoByIlIds = roomInnerService.getRoomInfoByIlIds(ilIdList);
            ilIdMap = roomInfoByIlIds.stream().collect(Collectors.toMap(RoomsEntityDTO::getIlId, RoomsEntityDTO::getSubject));
        }

        Map<Integer, String> finalIlIdMap = ilIdMap;
        page.getRecords().forEach(recordEntity -> uploadRspList.add(convertToUploadRspVo(recordEntity, finalIlIdMap)));
        getUploadListRspVo.setUploadRspList(uploadRspList);
        getUploadListRspVo.setCurrentPage(currPage);
        getUploadListRspVo.setLastPage((int) page.getPages());
        getUploadListRspVo.setPerPage(pageSize);
        getUploadListRspVo.setTotal((int) page.getTotal());
        getUploadListRspVo.setFrom((currPage - 1) * pageSize + 1);
        getUploadListRspVo.setTo(Math.min(currPage * pageSize, (int) page.getTotal()));

        int lastPage = (int) page.getPages();
        getUploadListRspVo.setFirstPageUrl("\\/?page=1");
        getUploadListRspVo.setLastPageUrl(PAGE_ESCAPE + (int) page.getPages());
        String prevPage = currPage == 1 ? null : PAGE_ESCAPE + (currPage - 1);
        String nextPage = currPage == lastPage ? null : PAGE_ESCAPE + (currPage + 1);
        getUploadListRspVo.setPrevPageUrl(prevPage);
        getUploadListRspVo.setNextPageUrl(nextPage);
        getUploadListRspVo.setPath("\\/");
        return getUploadListRspVo;
    }

    /**
     * 重命名音视频
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void renameUpload(RenameUploadReqVo reqVo) {
        RecordEntity recordEntity = recordMapper.selectOne(Wrappers.<RecordEntity>lambdaQuery().eq(RecordEntity::getVodId, reqVo.getRecordId()).last(LIMIT_0_1));
        if (recordEntity == null) {
            log.error("回放id：{}的视频不存在", reqVo.getRecordId());
            throw new BusinessException(BizErrorCode.EMPTY_VIDEO);
        }
        recordEntity.setUpdatedAt(LocalDateTime.now());
        recordEntity.setName(reqVo.getName());
        recordMapper.update(recordEntity, Wrappers.<RecordEntity>lambdaQuery().eq(RecordEntity::getId, recordEntity.getId()));
        //调用PAAS更改回放名称
        Map<String, Object> param = new HashMap<>(8);
        param.put("name", reqVo.getName());
        param.put(PaasCommonConstant.VOD_ID_KEY, reqVo.getRecordId());
        paasService.changeName(param);
    }

    /**
     * 获取音视频详情
     */
    @Override
    public JSONObject getUploadInfo(GetUploadInfoReqVo reqVo) {
        //调用PAAS获取音视频详情
        Map<String, Object> param = new HashMap<>(8);
        param.put(PaasCommonConstant.VOD_ID_KEY, reqVo.getRecordId());
        param.put("acquire_video_info", 1);
        JSONObject jsonObject = paasService.recordInfo(param);
        if (jsonObject != null) {
            JSONArray jsonArray = jsonObject.getJSONArray("video_info");
            JSONArray jsonArrayReturn = new JSONArray();
            if (jsonArray != null && !jsonArray.isEmpty()) {
                for (Object o : jsonArray) {
                    JSONObject object = (JSONObject) o;
                    String value = redisTemplate.opsForValue().get(RedisKey.RECORD_DOWN_QA_URL + reqVo.getRecordId() + ":" + object.getString("quality"));
                    if (StringUtils.isNotBlank(value)) {
                        object.put(DOWN_URL, value);
                    } else {
                        object.put(DOWN_URL, false);
                    }
                    jsonArrayReturn.add(object);
                }
            }
            jsonObject.put("video_info", jsonArrayReturn);
        }
        return jsonObject;
    }

    /**
     * 删除音视频的某个清晰度
     */
    @Override
    public JSONObject deleteVideo(DeleteVideoReqVo reqVo) {
        //调用PAAS删除某个清晰度
        Map<String, Object> param = new HashMap<>(8);
        param.put(PaasCommonConstant.VIDEO_ID_KEY, reqVo.getVid());
        param.put(PaasCommonConstant.VOD_ID_KEY, reqVo.getRecordId());
        return paasService.videoDel(param);
    }

    @Override
    public GetCutDetailRspVo getCutRecordDetail(GetCutDetailReqVo reqVo) {
        Token account = TokenThreadLocal.getToken();
        RecordEntity recordEntity = recordMapper.selectOne(Wrappers.<RecordEntity>lambdaQuery().eq(RecordEntity::getVodId, reqVo.getVodId()).last(LIMIT_0_1));
        if (recordEntity == null) {
            log.error("回放id：{}的回放信息不存在", reqVo.getVodId());
            throw new BusinessException(BizErrorCode.EMPTY_RECORD);
        } else {
            RoomsEntityDTO roomsEntity = roomInnerService.getRoomInfoByIlId(recordEntity.getIlId().toString());
            if (roomsEntity == null) {
                log.error("房间id：{}不存在", recordEntity.getIlId());
                throw new BusinessException(BizErrorCode.EMPTY_ROOM);
            } else {
                return convertToCutDetailRsp(recordEntity, roomsEntity.getChannelId(), appId, account.getAccountId());
            }
        }
    }

    /**
     * 转换成待裁剪的回放信息响应
     */
    private GetCutDetailRspVo convertToCutDetailRsp(RecordEntity recordEntity, String channelId, String appId, long accountId) {
        GetCutDetailRspVo getCutDetailRspVo = new GetCutDetailRspVo();
        getCutDetailRspVo.setId(recordEntity.getId());
        getCutDetailRspVo.setAccountId((int) accountId);
        getCutDetailRspVo.setIlId(recordEntity.getIlId());
        getCutDetailRspVo.setRoomId(recordEntity.getRoomId());
        getCutDetailRspVo.setSource(recordEntity.getSource());
        getCutDetailRspVo.setVodId(recordEntity.getVodId());
        getCutDetailRspVo.setName(recordEntity.getName());
        getCutDetailRspVo.setTranscodeStatus(recordEntity.getTranscodeStatus());
        getCutDetailRspVo.setDuration(recordEntity.getDuration());
        getCutDetailRspVo.setStorage(recordEntity.getStorage());
        getCutDetailRspVo.setStatus(recordEntity.getStatus());
        getCutDetailRspVo.setCreatedAt(LocalDateTimeUtil.formatNormal(recordEntity.getCreatedAt()));
        getCutDetailRspVo.setUpdatedAt(LocalDateTimeUtil.formatNormal(recordEntity.getUpdatedAt()));
        getCutDetailRspVo.setDeletedAt(null);
        getCutDetailRspVo.setCreatedTime(null);
        getCutDetailRspVo.setChannelId(channelId);
        getCutDetailRspVo.setAppId(appId);
        return getCutDetailRspVo;
    }

    @Override
    public RecordEntity saveRecord(CutRecordReqVO reqVO) {
        try {

            JSONObject result = paasService.saveRecord(reqVO);

            RecordEntity entity = new RecordEntity();
            if (result.containsKey(HttpConstant.DATA)) {

                String newVoidId = result.getJSONObject(HttpConstant.DATA).getString(PaasCommonConstant.VOD_ID_KEY);
                entity.setRoomId(reqVO.getStreamId());
                entity.setIlId(Integer.parseInt(reqVO.getIlId()));
                entity.setSource(11);
                entity.setAccountId(Integer.parseInt(reqVO.getAccountId()));
                entity.setVodId(newVoidId);
                entity.setTranscodeStatus(1);
                if (StringUtils.isNotBlank(reqVO.getName())) {
                    entity.setName(reqVO.getName());
                }
                entity.setDuration(0);
                entity.setStorage(0);
                entity.setCreatedAt(LocalDateTime.now());
                entity.setUpdatedAt(LocalDateTime.now());
                entity.setCreatedTime(LocalDateTime.now());
            }

            int effect = recordMapper.insert(entity);

            if (effect > 0) {
                return entity;
            }
        } catch (Exception e) {
            log.error("裁剪保存失败:[]" + JSON.toJSONString(reqVO), e);
            throw new BusinessException(BizErrorCode.COMP_RECORD_INSERT_FAILED);
        }
        return null;
    }

    @Override
    public JSONObject downRecord(RecordDownReqVO reqVO) {
        String recordId = reqVO.getRecordId();
        int num = recordMapper.getNumByRecordId(recordId);
        if (num == 0) {
            throw new BusinessException(BizErrorCode.EMPTY_VIDEO);
        }
        String value = redisTemplate.opsForValue().get(RedisKey.RECORD_DOWN_URL + reqVO.getRecordId());
        String downUrl = value;

        if (value == null && !"cache".equals(reqVO.getType())) {
            JSONObject result = paasService.downRecord(reqVO);
            result.get(HttpConstant.DATA).toString();
            try {
                TimeUnit.SECONDS.sleep(3);
                value = redisTemplate.opsForValue().get(RedisKey.RECORD_DOWN_URL + reqVO.getRecordId());
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new BusinessException(BizErrorCode.EMPTY_VIDEO);
            }
            JSONObject jo = new JSONObject();
            jo.put(DOWN_URL, value);
            return jo;
        }
        if (value != null) {
            JSONObject jo = new JSONObject();
            jo.put(DOWN_URL, downUrl);
            return jo;
        }
        return null;
    }


    @Override
    public JSONObject downRecordQuality(RecordDownQualityReqVO reqVO) {
        String recordId = reqVO.getRecordId();
        int num = recordMapper.getNumByRecordId(recordId);
        if (num == 0) {
            throw new BusinessException(BizErrorCode.EMPTY_VIDEO);
        }
        String value = redisTemplate.opsForValue().get(RedisKey.RECORD_DOWN_QA_URL + reqVO.getRecordId() + ":" + reqVO.getQuality());
        String downUrl = value;
        if (value == null && !"cache".equals(StringUtils.isNotBlank(reqVO.getType()) ? reqVO.getType() : "")) {
            JSONObject result = paasService.downRecordQuality(reqVO);
            result.get(HttpConstant.DATA).toString();
            try {
                TimeUnit.SECONDS.sleep(3);
                value = redisTemplate.opsForValue().get(RedisKey.RECORD_DOWN_QA_URL + reqVO.getRecordId() + ":" + reqVO.getQuality());
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new BusinessException(BizErrorCode.BIZ_DOWNLOAD_FAILED);
            }
            JSONObject jo = new JSONObject();
            jo.put(DOWN_URL, value);
            return jo;
        }
        if (value != null) {
            JSONObject jo = new JSONObject();
            jo.put(DOWN_URL, downUrl);
            return jo;
        }
        return null;
    }


    @Override
    public Boolean uploadRecord(CreateRecordReqVO reqVO) {
        if (null == reqVO.getIlId()) {
            reqVO.setIlId(0);
        }
        RecordDTO dto = new RecordDTO();
        dto.setRecordId(reqVO.getRecordId());
        dto.setIlId(reqVO.getIlId());
        dto.setName(reqVO.getName());
        dto.setSource(reqVO.getSource());
        dto.setAccountId(reqVO.getAccountId());
        RecordEntity entity = insertRecord(dto);
        return entity != null;
    }


    private RecordEntity insertRecord(RecordDTO dto) {

        Map<String, Object> params = new HashMap<>(8);
        params.put(PaasCommonConstant.VOD_ID_KEY, dto.getRecordId());
        JSONObject result = paasService.getVodInfo(params);

        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            return null;
        }

        JSONObject data = result.getJSONObject(HttpConstant.DATA);
        if (!data.containsKey(PaasCommonConstant.VOD_INFO_KEY)) {
            return null;
        }
        JSONObject vodNode = data.getJSONObject(PaasCommonConstant.VOD_INFO_KEY);

        LocalDateTime createAt = LocalDateTimeUtil.parse(vodNode.getString("created_at"), DatePattern.NORM_DATETIME_FORMATTER);
        String name = StringUtils.isEmpty(dto.getName()) ? vodNode.getString("name") : dto.getName();

        // 视频上传会为null, 但不能直接入入库, 否则会变成 0
        Integer source = dto.getSource() == null ? vodNode.getInteger("source") : dto.getSource();

        RecordEntity recordEntity = new RecordEntity();
        recordEntity.setName(name);
        recordEntity.setCreatedTime(createAt);
        recordEntity.setTranscodeStatus(vodNode.getInteger(TRANSCODE_STATUS));
        recordEntity.setStorage(vodNode.getInteger(STORAGE));
        recordEntity.setDuration(vodNode.getInteger(DURATION));
        recordEntity.setRoomId(vodNode.getString("room_id"));
        // 尽可能的将roomID数据填上，如果都查不到，上传的音视频就是无关联直播间，可能会作为直播间的暖场视频之类
        if (recordEntity.getRoomId() == null && dto.getIlId() != null) {
            RoomsEntityDTO roomInfoByIlId = roomInnerService.getRoomInfoByIlId(dto.getIlId().toString());
            recordEntity.setRoomId(roomInfoByIlId.getRoomId());
        }
        LocalDateTime now = LocalDateTime.now();
        recordEntity.setCreatedAt(now);
        recordEntity.setUpdatedAt(now);

        recordEntity.setSource(source);
        recordEntity.setIlId(dto.getIlId());
        recordEntity.setVodId(dto.getRecordId());
        recordEntity.setAccountId(Integer.parseInt(dto.getAccountId()));

        recordMapper.insert(recordEntity);
        return recordEntity;
    }

    @Override
    public GetVodInfoRspVO getVodInfo(GetVodInfoReqVO reqVO) {
        GetVodInfoRspVO rspVO = new GetVodInfoRspVO();

        LambdaQueryWrapper<RecordEntity> where = Wrappers.lambdaQuery();
        where.eq(RecordEntity::getVodId, reqVO.getRecordId());
        where.orderByDesc(RecordEntity::getUpdatedAt);
        where.last("limit 1");
        RecordEntity record = recordMapper.selectOne(where);
        if (record == null) {
            throw new BusinessException(BizErrorCode.EMPTY_VOD);
        }

        if (!record.getStorage().equals(0) && !record.getDuration().equals(0)) {
            BeanUtils.copyProperties(record, rspVO);
            rspVO.setDuration(record.getDuration().toString());
            rspVO.setAppId(appId);
            return rspVO;
        }
        HashMap<String, Object> param = new HashMap<>(8);
        param.put(PaasCommonConstant.VOD_ID_KEY, record.getVodId());
        JSONObject recordInfo = paasService.recordInfo(param);
        if (recordInfo != null && recordInfo.containsKey(PaasCommonConstant.VOD_INFO_KEY)) {
            log.info("查询paas出来的数据为：" + recordInfo.toJSONString());
            JSONObject vodInfo = recordInfo.getJSONObject(PaasCommonConstant.VOD_INFO_KEY);
            Integer status = vodInfo.getInteger(STATUS);
            log.info("获取到的状态,{}", status);
            if (vodSuccessStatus.contains(status)) {
                JSONObject field = new JSONObject();
                field.put(DURATION, vodInfo.get(DURATION));
                if (!record.getSource().equals(RecordConstant.SOURCE_CUTTING)) {
                    field.put(TRANSCODE_STATUS, vodInfo.get(TRANSCODE_STATUS));
                }
                field.put(STORAGE, vodInfo.get(STORAGE));
                if (StringUtils.isBlank(record.getName())) {
                    field.put("name", vodInfo.get("name"));
                }
                RecordEntity res = completeById(record, field);
                if (res == null) {
                    throw new BusinessException(BizErrorCode.EMPTY_DATA);
                }
                BeanUtils.copyProperties(res, rspVO);
                rspVO.setDuration(res.getDuration().toString());

                rspVO.setAppId(appId);
                log.info("最后生成的数据为：{}" + JSON.toJSONString(rspVO));
                return rspVO;
            } else if (vodErrorStatus.contains(status)) {
                log.info("异常数据为：" + vodInfo.toJSONString());
                if (3 == status) {
                    recordMapper.deleteById(record.getId());
                    //调用PAAS服务删除回放
                    Map<String, Object> recordDelParam = new HashMap<>(8);
                    recordDelParam.put(PaasCommonConstant.VOD_ID_KEY, reqVO.getRecordId());
                    paasService.recordDel(recordDelParam);
                }
                throw new BusinessException(BizErrorCode.BIZ_GENERATE_FAILED);
            } else if (status == 0) {
                log.info("获取到的数据是初始化的数据");
                //如果发现是初始化状态，则等待3s 继续查询
                try {
                    //MILLISECONDS表示以毫秒为单位延时
                    TimeUnit.MILLISECONDS.sleep(5000);
                    return getVodInfo(reqVO);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    public JSONObject getCutList(CutListReqVO reqVO) {
        try {
            if (reqVO.getPage() == null) {
                reqVO.setPage(0);
            }
            if (reqVO.getPageSize() == null) {
                reqVO.setPageSize(100);
            }
            Token token = TokenThreadLocal.getToken();
            if (token.getRoleType() == 1) {
                reqVO.setAccountId(null);
            } else if (token.getRoleType() == 2) {
                LambdaQueryWrapper<AccountEntity> queryWrapper = Wrappers.lambdaQuery();
                queryWrapper.eq(AccountEntity::getOrgCode, token.getOrgCode());
                List<AccountEntity> accountEntities = accountMapper.selectList(queryWrapper);
                List<Integer> accountIds = accountEntities.stream().map(AccountEntity::getAccountId).collect(Collectors.toList());
                reqVO.setAccountIds(accountIds);
                reqVO.setAccountId(null);
            }

            List<CutListRspVO> list = recordMapper.selectCutList(reqVO);
            Integer total = recordMapper.selectCutListCount(reqVO);
            List<Integer> ilIdlist = new ArrayList<>();
            for (CutListRspVO clrv : list) {
                ilIdlist.add(clrv.getIlId());
            }
            if (ilIdlist.size() > 0) {
                List<RoomRspVO> roomList = roomInnerService.selectRoomList(ilIdlist);
                for (CutListRspVO clrv : list) {
                    for (RoomRspVO rsvo : roomList) {
                        if (rsvo.getIlId().intValue() == clrv.getIlId().intValue()) {
                            clrv.setRoomId(rsvo.getRoomId());
                            clrv.setChannelId(rsvo.getChannelId());
                            clrv.setDuration(DateUtils.secToTime(clrv.getDurationSecond()));
                        }
                    }
                    clrv.setDuration(DateUtils.secToTime(clrv.getDurationSecond()));
                    clrv.setAppId(appId);
                }
            }
            JSONObject jo = new JSONObject();
            jo.put("total", total);
            jo.put("per_page", reqVO.getPageSize());
            jo.put("page", reqVO.getPage());
            jo.put("list", list);
            return jo;
        } catch (Exception e) {
            log.info("select record is error,the e is ", e);
            throw new BusinessException(BizErrorCode.EMPTY_DATA);
        }

    }

    @Override
    public RecordEntity cutMergeRecord(CutMergeRecordReqVO reqVO) {
        Token token = TokenThreadLocal.getToken();
        if (token.getRoleType() == 2) {
            LambdaQueryWrapper<AccountEntity> queryWrapper = Wrappers.lambdaQuery();
            queryWrapper.eq(AccountEntity::getOrgCode, token.getOrgCode());
            List<AccountEntity> accountEntities = accountMapper.selectList(queryWrapper);
            List<Integer> accountIds = accountEntities.stream().map(AccountEntity::getAccountId).collect(Collectors.toList());

            LambdaQueryWrapper<RoomsEntity> roomsEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
            roomsEntityLambdaQueryWrapper.in(RoomsEntity::getAccountId, accountIds);
            List<RoomsEntity> roomsEntities = roomMapper.selectList(roomsEntityLambdaQueryWrapper);
            Set<Integer> collect = roomsEntities.stream().map(RoomsEntity::getIlId).collect(Collectors.toSet());
            if (!collect.contains(Integer.parseInt(reqVO.getIlId()))) {
                return null;
            }
        }

        RoomsEntityDTO room = roomInnerService.getRoomInfoByIlId(reqVO.getIlId());
        if (room == null || StringUtils.isBlank(room.getRoomId())) {
            throw new BusinessException(BizErrorCode.EMPTY_ROOM);
        }

        if (room.getStatus().equals(RoomStatusEnum.TO_BE_BROADCAST.getStatus())) {
            throw new BusinessException(BizErrorCode.BIZ_SOURCE_NOT_START);
        }

        JSONObject result = paasService.createRecord(room.getRoomId(), reqVO.getStartTime(), reqVO.getEndTime());
        if (result.getInteger(HttpConstant.CODE) != HttpConstant.SUCCESS_CODE) {
            log.warn("生成回放失败,{}", result);
            throw new BusinessException(BizErrorCode.BIZ_GENERATE_FAILED);
        }

        JSONObject mergeInfo = result.getJSONObject(HttpConstant.DATA);
        if (null == mergeInfo) {
            throw new BusinessException(BizErrorCode.BIZ_GENERATE_FAILED);
        }

        String vodId = mergeInfo.getString(PaasCommonConstant.VOD_ID_KEY);
        // 0=回放, 10=合成
        int source = null != reqVO.getSource() ? 0 : 10;

        RecordDTO dto = new RecordDTO();
        dto.setAccountId(reqVO.getAccountId());
        dto.setIlId(Integer.parseInt(reqVO.getIlId()));
        dto.setSource(source);
        dto.setRecordId(vodId);
        if (source < 1) {
            dto.setName(room.getRoomId() + reqVO.getStartTime());
        }
        RecordEntity recordEntity = insertRecord(dto);
        if (null == recordEntity) {
            throw new BusinessException(BizErrorCode.BIZ_GENERATE_FAILED);
        }
        return recordEntity;
    }

    @TokenAuth
    @Override
    public JSONObject deleteUpload(DeleteUploadReqVo reqVo) {
        String[] arr = reqVo.getRecordId().split(",");
        List<String> list = Arrays.asList(arr);
        //先根据回放id查询回放记录
        final List<RecordEntity> recordEntities = recordMapper.selectList(Wrappers.<RecordEntity>lambdaQuery().in(RecordEntity::getVodId, list));
        for (RecordEntity recordEntity : recordEntities) {
            //判断当前回放 是否是房间的默认回放
            RoomsEntityDTO roomsEntity = roomInnerService.getRoomInfo(recordEntity.getRoomId());
            if (roomsEntity != null && (list.contains(roomsEntity.getRecordId())
                    || list.contains(roomsEntity.getWarmVodId())
                    || list.contains(roomsEntity.getDemandVodId()))) {
                throw new BusinessException(BizErrorCode.COMP_UPLOAD_DEL_FAIL);
            }

            // 如果当前视频，短视频使用/录播房间使用，也禁止删除
            LambdaQueryWrapper<RoomsEntity> wrapper = Wrappers.lambdaQuery();

            wrapper.and(andWrapper -> andWrapper.eq(RoomsEntity::getDemandVodId, recordEntity.getVodId())
                    .or().eq(RoomsEntity::getRecordId, recordEntity.getVodId()));
            List<RoomsEntity> roomsEntities = roomMapper.selectList(wrapper);
            if (CollectionUtils.isNotEmpty(roomsEntities)) {
                throw new BusinessException(BizErrorCode.COMP_UPLOAD_DEL_FAIL);
            }
        }

        //执行删除
        int rowEffect = recordMapper.delete(Wrappers.<RecordEntity>lambdaQuery().in(RecordEntity::getVodId, list));
        if (rowEffect == 0) {
            log.error("删除音视频：{}失败", reqVo.getRecordId());
            throw new BusinessException(BizErrorCode.BIZ_DELETE_FAILED);
        }

        //调用PAAS服务删除回放
        Map<String, Object> param = new HashMap<>(8);
        param.put(PaasCommonConstant.VOD_ID_KEY, reqVo.getRecordId());
        return paasService.recordDel(param);
    }

    @Override
    public void insert(RecordEntityDTO recordEntity) {
        RecordEntity e = new RecordEntity();
        BeanUtils.copyProperties(recordEntity, e);
        recordMapper.insert(e);
    }

    @Override
    public void updateById(RecordEntityDTO recordEntity) {
        RecordEntity e = new RecordEntity();
        BeanUtils.copyProperties(recordEntity, e);
        recordMapper.updateById(e);
    }

    @Override
    public RecordEntityDTO findByVodId(String vodId) {
        RecordEntity e = recordMapper.findByVodId(vodId);
        RecordEntityDTO ed = new RecordEntityDTO();
        BeanUtils.copyProperties(e, ed);
        return ed;
    }

    @Override
    public void setWilfullyRecord(SetDefaultRecordReqVo reqVO) {
        //查询回放信息
        RecordEntity recordEntity = recordMapper.selectOne(Wrappers.<RecordEntity>lambdaQuery().eq(RecordEntity::getVodId, reqVO.getRecordId()).last(LIMIT_0_1));
        if (recordEntity == null) {
            log.error("房间id：{}，回放id：{}的回放信息不存在", reqVO.getRoomId(), reqVO.getRecordId());
            throw new BusinessException(BizErrorCode.EMPTY_RECORD);
        }
        int count = roomInnerService.getCountByIlidAndRecordId(recordEntity.getIlId().toString(), reqVO.getRecordId());
        //默认回放ID，空为取消默认回放
        String recordId = count > 0 ? "" : reqVO.getRecordId();
        RoomsEntityDTO roomsEntity = roomInnerService.getRoomInfo(reqVO.getRoomId());
        roomsEntity.setRecordId(recordId);
        int rowEffect = roomInnerService.updateByIl(roomsEntity);
        if (rowEffect == 0) {
            log.error("房间id：{}的回放信息不存在", reqVO.getRoomId());
            throw new BusinessException(BizErrorCode.COMP_RECORD_UPDATE_FAILED);
        }
    }

    @Override
    public Boolean addRecord(GetRecordListReqVo reqVo) {
        Preconditions.checkArgument(StringUtils.isNotBlank(reqVo.getRecordId()), "回放id不能为空！");

        LambdaQueryWrapper<RecordEntity> where = Wrappers.lambdaQuery();
        where.eq(RecordEntity::getVodId, reqVo.getRecordId());
        RecordEntity recordEntity = recordMapper.selectOne(where);

        Preconditions.checkArgument(recordEntity != null, "没有当前回放！");
        Preconditions.checkArgument((recordEntity.getIlId() == null || recordEntity.getIlId() == 0)
                && StringUtils.isBlank(recordEntity.getRoomId())
                && recordEntity.getSource() == 1, "当前回放已经关联房间！");


        RoomsEntityDTO roomsEntity = roomInnerService.getRoomInfo(reqVo.getRoomId());
        Preconditions.checkArgument(roomsEntity != null, "房间不存在！");

        recordEntity.setCreatedTime(LocalDateTime.now());
        recordEntity.setRoomId(reqVo.getRoomId());
        LocalDateTime now = LocalDateTime.now();
        recordEntity.setCreatedAt(now);
        recordEntity.setUpdatedAt(now);
        recordEntity.setIlId(roomsEntity.getIlId());
//        recordEntity.setSource(0);
        recordMapper.updateById(recordEntity);
        return true;
    }

    @Override
    public boolean doAuditRoomRecord(Integer ilId, Integer recordId, Integer auditStatus, String description) {
        RecordEntity recordEntity = new RecordEntity();
        recordEntity.setAuditStatus(auditStatus);
        recordEntity.setId(recordId);
        recordEntity.setUpdatedAt(LocalDateTime.now());
        if (recordMapper.updateById(recordEntity) > 0) {
            RecordEntity record = recordMapper.selectById(recordId);
            RoomsEntity roomsEntity = roomMapper.selectById(ilId);
            if (roomsEntity.getRecordId().equals(record.getVodId())) {
                LambdaUpdateWrapper<RoomsEntity> queryWrapper = Wrappers.lambdaUpdate();
                queryWrapper.eq(RoomsEntity::getIlId, roomsEntity.getIlId());
                queryWrapper.set(RoomsEntity::getPlaybackStatus, auditStatus);
                queryWrapper.set(RoomsEntity::getPlaybackNote, description);
                queryWrapper.set(RoomsEntity::getPlaybackStatusSecond, RoomAuditStatusEnum.CHECK_PENDING.getAuditStatus());
                queryWrapper.set(RoomsEntity::getPlaybackNoteSecond, "");
                roomMapper.update(null, queryWrapper);
            }
            redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + roomsEntity.getRoomId());
            redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + ilId);

            CreateAuditRecordDTO dto = new CreateAuditRecordDTO();
            dto.setAuditStatus(auditStatus);
            dto.setAuditTableRecordId(recordId.toString());
            dto.setAuditComments(description);
            dto.setAuditTable("record");
            auditRecordService.createAuditRecord(dto);
            if (Objects.equals(RoomAuditStatusEnum.APPROVED.getAuditStatus(),auditStatus)) {
                LambdaQueryWrapper<RoomReservationThirdEntity> roomReservationThirdEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
                roomReservationThirdEntityLambdaQueryWrapper.eq(RoomReservationThirdEntity::getIlId, roomsEntity.getIlId());
                if (roomReservationThirdMapper.selectCount(roomReservationThirdEntityLambdaQueryWrapper) > 0) {
                    LambdaUpdateWrapper<RoomReservationThirdEntity> updateWrapper = Wrappers.lambdaUpdate();
                    updateWrapper.eq(RoomReservationThirdEntity::getIlId, ilId);
                    updateWrapper.set(RoomReservationThirdEntity::getHavePlayback, 1);
                    roomReservationThirdMapper.update(null, updateWrapper);
                }
//                产品类型的房间才进行二次审核
                if (Objects.equals(LiveContentTypeEnum.TYPE_3.getValue(),roomsEntity.getLiveContentType())) {
                    String complianceAuditorsCode = roomsEntity.getComplianceAuditorsCode();
                    if (StrUtil.isNotBlank(complianceAuditorsCode)) {
                        RoomPushMsgThirdEntity roomPushMsgThirdEntity = buildRoomPushMsgThirdEntity(roomsEntity, record, RoomPushMsgTypeEnum.SECOND_TRIAL_NOTIFICATION, complianceAuditorsCode);
                        roomPushMsgThirdService.save(roomPushMsgThirdEntity);
                    }else{
                        log.info("当前直播间:{},未设置合规审核人员编号",ilId);
                    }
                }
            }
            return true;
        }

        return false;
    }

    @Override
    public boolean doAuditRoomRecordSecond(Integer ilId, Integer recordId, Integer auditStatus, String description) {
        RecordEntity recordEntity = new RecordEntity();
        recordEntity.setAuditStatusSecond(auditStatus);
        recordEntity.setId(recordId);
        recordEntity.setUpdatedAt(LocalDateTime.now());
        if (recordMapper.updateById(recordEntity) > 0) {
            RecordEntity record = recordMapper.selectById(recordId);
            RoomsEntity roomsEntity = roomMapper.selectById(ilId);
            if (roomsEntity.getRecordId().equals(record.getVodId())){
                roomsEntity.setPlaybackStatusSecond(auditStatus);
                roomsEntity.setPlaybackNoteSecond(description);
                roomMapper.updateById(roomsEntity);
            }
            redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + roomsEntity.getRoomId());
            redisTemplate.delete(RedisKey.ROOM_INFO_BY_ROOM_ID + ilId);

            CreateAuditRecordDTO dto = new CreateAuditRecordDTO();
            dto.setAuditStatus(auditStatus);
            dto.setAuditTableRecordId(recordId.toString());
            dto.setAuditComments(description);
            dto.setAuditTable("record");
            dto.setAuditRounds(2);
            return auditRecordService.createAuditRecord(dto);
        }

        return false;
    }

    @Override
    public AuditRecordResponseVO auditInfo(Integer recordId) {
        return auditRecordService.getAuditRecord(recordId.toString(), "record",1);
    }

    @Override
    public AuditRecordResponseVO auditInfoSecond(Integer recordId) {
        return auditRecordService.getAuditRecord(recordId.toString(), "record",2);
    }

    @Override
    public GetRecordListRspVo getAuditList(GetRecordListReqVo reqVo) {
        GetRecordListRspVo result = new GetRecordListRspVo();
        int currPage = reqVo.getPage() == null ? 1 : reqVo.getPage();
        int pageSize = reqVo.getPageSize() == null ? 10 : reqVo.getPageSize();
        LambdaQueryWrapper<RoomsEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(RoomsEntity::getRoomId, reqVo.getRoomId());
        queryWrapper.last(" limit 1");
        RoomsEntity roomsEntity = roomMapper.selectOne(queryWrapper);
        LambdaQueryWrapper<RecordEntity> recordEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
        recordEntityLambdaQueryWrapper.eq(RecordEntity::getIlId, roomsEntity.getIlId());
        recordEntityLambdaQueryWrapper.in(RecordEntity::getSource, "10", "11", "1", "0");
        recordEntityLambdaQueryWrapper.lt(RecordEntity::getAuditStatus, 9);
        recordEntityLambdaQueryWrapper.groupBy(RecordEntity::getVodId);
        //查询回放列表
        Page<RecordEntity> page = new Page<>(currPage, pageSize);
        page = recordMapper.selectPage(page, recordEntityLambdaQueryWrapper);

        List<RecordRsp> recordRspList = new ArrayList<>();
        page.getRecords().forEach(recordEntity -> recordRspList.add(convertToRecordRspVo(recordEntity
                , roomsEntity.getRecordId()
                , roomsEntity.getLiveContentType().equals(LiveContentTypeEnum.TYPE_3.getValue()))));
        result.setRecordRspList(recordRspList);
        result.setCurrentPage(currPage);
        result.setLastPage((int) page.getPages());
        result.setPerPage(String.valueOf(pageSize));
        result.setTotal((int) page.getTotal());
        result.setFrom((currPage - 1) * pageSize + 1);
        result.setTo(Math.min(currPage * pageSize, (int) page.getTotal()));

        int lastPage = (int) page.getPages();
        result.setFirstPageUrl("\\/?page=1");
        result.setLastPageUrl(PAGE_ESCAPE + (int) page.getPages());
        String prevPage = currPage == 1 ? null : PAGE_ESCAPE + (currPage - 1);
        String nextPage = currPage == lastPage ? null : PAGE_ESCAPE + (currPage + 1);
        result.setPrevPageUrl(prevPage);
        result.setNextPageUrl(nextPage);
        result.setPath("\\/");
        return result;
    }

    @Override
    public GetRecordListRspVo getAuditListSecond(GetRecordListReqVo reqVo) {
        GetRecordListRspVo result = new GetRecordListRspVo();
        int currPage = reqVo.getPage() == null ? 1 : reqVo.getPage();
        int pageSize = reqVo.getPageSize() == null ? 10 : reqVo.getPageSize();
        LambdaQueryWrapper<RoomsEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(RoomsEntity::getRoomId, reqVo.getRoomId());
        queryWrapper.last(" limit 1");
        RoomsEntity roomsEntity = roomMapper.selectOne(queryWrapper);
        LambdaQueryWrapper<RecordEntity> recordEntityLambdaQueryWrapper = Wrappers.lambdaQuery();
        recordEntityLambdaQueryWrapper.eq(RecordEntity::getIlId, roomsEntity.getIlId());
        recordEntityLambdaQueryWrapper.in(RecordEntity::getSource, "10", "11", "1", "0");
        recordEntityLambdaQueryWrapper.eq(RecordEntity::getAuditStatus, RoomAuditStatusEnum.APPROVED.getAuditStatus());
        recordEntityLambdaQueryWrapper.groupBy(RecordEntity::getVodId);
        //查询回放列表
        Page<RecordEntity> page = new Page<>(currPage, pageSize);
        page = recordMapper.selectPage(page, recordEntityLambdaQueryWrapper);

        List<RecordRsp> recordRspList = new ArrayList<>();
        page.getRecords().forEach(recordEntity -> recordRspList.add(convertToRecordRspVo(recordEntity
                , roomsEntity.getRecordId()
                , roomsEntity.getLiveContentType().equals(LiveContentTypeEnum.TYPE_3.getValue()))));
        result.setRecordRspList(recordRspList);
        result.setCurrentPage(currPage);
        result.setLastPage((int) page.getPages());
        result.setPerPage(String.valueOf(pageSize));
        result.setTotal((int) page.getTotal());
        result.setFrom((currPage - 1) * pageSize + 1);
        result.setTo(Math.min(currPage * pageSize, (int) page.getTotal()));

        int lastPage = (int) page.getPages();
        result.setFirstPageUrl("\\/?page=1");
        result.setLastPageUrl(PAGE_ESCAPE + (int) page.getPages());
        String prevPage = currPage == 1 ? null : PAGE_ESCAPE + (currPage - 1);
        String nextPage = currPage == lastPage ? null : PAGE_ESCAPE + (currPage + 1);
        result.setPrevPageUrl(prevPage);
        result.setNextPageUrl(nextPage);
        result.setPath("\\/");
        return result;
    }

    @Override
    public RoomConsoleListRespVO auditRoomList(Integer accountId, RoomConsoleListVO reqVO) {
        RoomConsoleListRespVO resp = new RoomConsoleListRespVO();
        int currPage = reqVO.getPage() == null ? 1 : reqVO.getPage();
        int pageSize = reqVO.getPageSize() == null ? 20 : reqVO.getPageSize();
        Page<RoomsEntity> page = new Page<>(currPage, pageSize);


        Token token = TokenThreadLocal.getToken();
        page = roomMapper.selectAnchorRoomList(page, token.getThirdPartyUserId(), reqVO.getPlaybackStatus(), reqVO.getKeyword());

        List<RoomsEntityVO> rooms = roomsEntityToListVo(page);
        resp.setRoomList(rooms);
        resp.setCurrentPage(currPage);
        resp.setLastPage((int) page.getPages());
        resp.setPerPage(pageSize);
        resp.setTotal((int) page.getTotal());
        resp.setFrom((currPage - 1) * pageSize + 1);
        resp.setTo(Math.min(currPage * pageSize, (int) page.getTotal()));
        int lastPage = (int) page.getPages();
        resp.setFirstPageUrl("\\/?page=1");
        resp.setLastPageUrl(RoomConstant.PAGE_ESCAPE + (int) page.getPages());
        String prevPage = currPage == 1 ? null : RoomConstant.PAGE_ESCAPE + (currPage - 1);
        String nextPage = currPage == lastPage ? null : RoomConstant.PAGE_ESCAPE + (currPage + 1);
        resp.setPrevPageUrl(prevPage);
        resp.setNextPageUrl(nextPage);
        resp.setPath("\\/");
        return resp;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public SaveRecordChapterManagementResponseVO saveRecordChapterManagement(SaveRecordChapterManagementRequestVO reqVO) {
        AddKeyFrameDescReqVO addKeyFrameDescReqVO = new AddKeyFrameDescReqVO();
        String pointSections = reqVO.getPointSections();
        String vodId = reqVO.getVodId();
        Integer ilId = reqVO.getIlId();
        RoomsEntityDTO roomInfoById = Optional.ofNullable(roomInnerService.getRoomInfoById(ilId)).orElseThrow(()->new BusinessException(BizErrorCode.EMPTY_ROOM));
        RecordEntity recordEntity = Optional.ofNullable(recordMapper.findByVodId(vodId)).orElseThrow(()->new BusinessException(BizErrorCode.EMPTY_RECORD));
        if (!Objects.equals(RoomAuditStatusEnum.APPROVED.getAuditStatus(),recordEntity.getAuditStatus())) {
//            回放未通过审核,不能进行章节打点
            throw new BusinessException(BizErrorCode.RECORD_FAILED_REVIEW_CANNOT_CHAPTER);
        }
        String roomId = roomInfoById.getRoomId();
        addKeyFrameDescReqVO.setPointSections(pointSections);
        addKeyFrameDescReqVO.setVodId(vodId);
        JSONArray pointSectionsJsonArray = null;
        try {
            if (StringUtils.isNotBlank(pointSections)) {
                pointSectionsJsonArray = JSON.parseArray(pointSections);
            }else{
                throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
            }
        } catch (Exception e) {
            throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
        }
//        处理打点数据
        if (pointSectionsJsonArray != null && !pointSectionsJsonArray.isEmpty()) {
            for (int i = 0; i < pointSectionsJsonArray.size(); i++) {
                JSONObject object = pointSectionsJsonArray.getJSONObject(i);
                String timePoint = object.get("timePoint").toString();
                String msg = object.get(HttpConstant.MSG).toString();
                if (StringUtils.isBlank(timePoint) || StringUtils.isBlank(msg)) {
                    throw new BusinessException(BizErrorCode.BIZ_INVALID_PARAM);
                }
            }
        }
        LambdaQueryWrapper<RecordChapterEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(RecordChapterEntity::getRecordId, vodId);
        List<RecordChapterEntity> recordChapterOldList = recordChapterMapper.selectList(queryWrapper);

        List<RecordChapterEntity> recordChapterEntities = buildRecordChapterList(vodId, ilId, roomId, pointSectionsJsonArray);
        long count = recordChapterEntities.stream().map(RecordChapterEntity::getTimePoint).count();
        if(count!=recordChapterEntities.size()){
//            章节打点中有重复时间
            throw new BusinessException(BizErrorCode.COMP_RECORD_CHAPTER_POINT_REPEAT);
        }
//        新增的章节
        List<RecordChapterEntity> newChapterList = null;
//        删除的章节打点
        List<RecordChapterEntity> delChapterList = null;
//        需要修改的章节
        List<RecordChapterEntity> updateChapterList = null;
        LocalDateTime now = LocalDateTime.now();
        if (CollUtil.isNotEmpty(recordChapterOldList)) {
            newChapterList = recordChapterEntities.stream().filter(data->{
                for (RecordChapterEntity recordChapterEntity : recordChapterOldList) {
                    if (Objects.equals(recordChapterEntity.getTimePoint(),data.getTimePoint())) {
                        return false;
                    }
                }
                return true;
            }).collect(Collectors.toList());
            updateChapterList = recordChapterEntities.stream().filter(data->{
                for (RecordChapterEntity recordChapterEntity : recordChapterOldList) {
                    if (Objects.equals(recordChapterEntity.getTimePoint(),data.getTimePoint())) {
                        return true;
                    }
                }
                return false;
            }).map(data->{
                for (RecordChapterEntity recordChapterEntity : recordChapterOldList) {
                    if (Objects.equals(recordChapterEntity.getTimePoint(),data.getTimePoint())) {
                        recordChapterEntity.setTimePoint(data.getTimePoint());
                        recordChapterEntity.setImage(data.getImage());
                        recordChapterEntity.setMsg(data.getMsg());
                        recordChapterEntity.setUpdatedAt(now);
                        return recordChapterEntity;
                    }
                }
                return data;
            }).collect(Collectors.toList());
            delChapterList = recordChapterOldList.stream().filter(data->{
                for (RecordChapterEntity recordChapterEntity : recordChapterEntities) {
                    if (Objects.equals(recordChapterEntity.getTimePoint(),data.getTimePoint())) {
                        return false;
                    }
                }
                return true;
            }).collect(Collectors.toList());
        }else{
            newChapterList = recordChapterEntities;
        }
//        创建需要新增的打点信息
        if (CollUtil.isNotEmpty(newChapterList)) {
            recordChapterService.saveBatch(newChapterList);
        }
//        更新原有的打点信息
        if (CollUtil.isNotEmpty(updateChapterList)) {
            recordChapterService.updateBatchById(updateChapterList);
        }
//        删除原本存在现在不存在的打点信息
        if (CollUtil.isNotEmpty(delChapterList)) {
            List<Integer> delIds = delChapterList.stream().map(RecordChapterEntity::getId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(delIds)) {
                LambdaQueryWrapper<RecordChapterEntity> deleteQueryWrapper = Wrappers.lambdaQuery();
                deleteQueryWrapper.eq(RecordChapterEntity::getRecordId,reqVO.getVodId())
                        .in(RecordChapterEntity::getId,delIds);
                recordChapterMapper.delete(deleteQueryWrapper);

            }
        }
        JSONArray newPointSectionsJsonArray = new JSONArray();
        for (RecordChapterEntity recordChapterEntity : recordChapterEntities) {
            JSONObject newPointSectionsJsonObject = new JSONObject();
            newPointSectionsJsonObject.put("time_point",recordChapterEntity.getTimePoint());
            newPointSectionsJsonObject.put("desc",recordChapterEntity.getMsg());
            newPointSectionsJsonArray.add(newPointSectionsJsonObject);
        }
        String newPointSections = newPointSectionsJsonArray.toJSONString();
        addKeyFrameDescReqVO.setPointSections(newPointSections);
        paasService.addKeyFrameDesc(addKeyFrameDescReqVO);
        SaveRecordChapterManagementResponseVO result = new SaveRecordChapterManagementResponseVO();
        result.setId(recordEntity.getId());
        result.setVodId(recordEntity.getVodId());
        return result;
    }

    @NotNull
    private List<RecordChapterEntity> buildRecordChapterList(String vodId, Integer ilId, String roomId, JSONArray pointSectionsJsonArray) {
        List<RecordChapterEntity> recordChapterEntities = new ArrayList<>();
        int size = pointSectionsJsonArray.size();
        for (int i = 0; i < size; i++) {
            JSONObject pointSectionsJsonObject = pointSectionsJsonArray.getJSONObject(i);
            String image = pointSectionsJsonObject.getString("image");
            String msg = pointSectionsJsonObject.getString("msg");
            int timePoint = pointSectionsJsonObject.getInteger("timePoint");
            RecordChapterEntity recordChapterEntity = new RecordChapterEntity();
            recordChapterEntity.setImage(image);
            recordChapterEntity.setMsg(msg);
            recordChapterEntity.setTimePoint(timePoint);
            recordChapterEntity.setRecordId(vodId);
            recordChapterEntity.setRoomId(roomId);
            recordChapterEntity.setIlId(ilId);
            recordChapterEntities.add(recordChapterEntity);
        }
        return recordChapterEntities;
    }

    @Override
    public SetPointStatusResponseVO setPointStatus(SetPointStatusRequestVO reqVO) {
        RoomsEntityDTO roomInfo = Optional.ofNullable(roomInnerService.getRoomInfo(reqVO.getRoomId())).orElseThrow(()->new BusinessException(BizErrorCode.EMPTY_ROOM));
        String vodId = reqVO.getVodId();
        RecordEntity recordEntity = Optional.ofNullable(recordMapper.findByVodId(vodId)).orElseThrow(() -> new BusinessException(BizErrorCode.EMPTY_RECORD));
        if (!Objects.equals(recordEntity.getIlId(),roomInfo.getIlId())) {
            throw new BusinessException(BizErrorCode.COMP_RECORD_NOT_BELONG_ROOM);
        }
        recordEntity.setRecordChapterStatus(reqVO.getPointStatus());
        int updateById = recordMapper.updateById(recordEntity);
        if (updateById<1) {
            throw new BusinessException(BizErrorCode.COMP_RECORD_UPDATE_FAILED);
        }
        String key = RedisKey.RECORD_INFO_ID + vodId;
        redisTemplate.delete(key);
        SetPointStatusResponseVO result = new SetPointStatusResponseVO();
        result.setVodId(vodId);
        return result;
    }

    @Override
    public RecordChapterListResponseVO getRecordChapterList(RecordChapterListRequestVO reqVO) {
        String roomId = reqVO.getRoomId();
        String recordId = reqVO.getRecordId();
        String key = RedisKey.RECORD_CHAPTER_LIST_KEY + recordId;
        RecordChapterListResponseVO result ;
        if (redisTemplate.hasKey(key)) {
            String resultStr = redisTemplate.opsForValue().get(key);
            result = JSONObject.parseObject(resultStr,RecordChapterListResponseVO.class);
        }else{
            result = getRecordChapterListMain(roomId, recordId);
            String cacheValue = JSON.toJSONString(result);
            redisTemplate.opsForValue().set(key,cacheValue,10,TimeUnit.SECONDS);
        }
        return result;
    }

    private RecordChapterListResponseVO getRecordChapterListMain(String roomId, String recordId) {
        RecordChapterListResponseVO result = new RecordChapterListResponseVO();
        RoomsEntityDTO roomInfo = Optional.ofNullable(roomInnerService.getRoomInfo(roomId)).orElseThrow(()->new BusinessException(BizErrorCode.EMPTY_ROOM));
        RecordEntity recordEntity = Optional.ofNullable(recordMapper.findByVodId(recordId)).orElseThrow(() -> new BusinessException(BizErrorCode.EMPTY_RECORD));
        if (!Objects.equals(recordEntity.getIlId(),roomInfo.getIlId())) {
            throw new BusinessException(BizErrorCode.COMP_RECORD_NOT_BELONG_ROOM);
        }
        LambdaQueryWrapper<RecordChapterEntity> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(RecordChapterEntity::getRecordId,recordEntity.getVodId())
                .orderByAsc(RecordChapterEntity::getTimePoint);
        List<RecordChapterEntity> recordChapterEntities = recordChapterMapper.selectList(queryWrapper);
        result.setRecordId(recordId);
        result.setId(recordEntity.getId());
        result.setRoomId(roomId);
        if (CollUtil.isNotEmpty(recordChapterEntities)) {
            List<PointSection> pointSectionList = recordChapterEntities.stream().map(data->{
                PointSection temp = new PointSection();
                temp.setImage(data.getImage());
                temp.setTimePoint(data.getTimePoint());
                temp.setMsg(data.getMsg());
                temp.setTimePoint2(DateTimeUtils.secondToTimeFormatStrHHMMSS(data.getTimePoint()));
                return temp;
            }).collect(Collectors.toList());
            result.setPointSections(pointSectionList);
        }
        return result;
    }


    private LambdaQueryWrapper<RoomsEntity> assemblyWrapper(RoomConsoleListVO reqVO) {
        Token token = TokenThreadLocal.getToken();
        LambdaQueryWrapper<RoomsEntity> wrapper = Wrappers.lambdaQuery();

        wrapper.orderByDesc(RoomsEntity::getStartTime);

        String keyword = reqVO.getKeyword();
        wrapper.and(StringUtils.isNotBlank(keyword), r -> r.like(RoomsEntity::getSubject, keyword)
                .or()
                .like(RoomsEntity::getIlId, keyword)
                .or()
                .apply("EXISTS(SELECT anchor_room_relation.id FROM anchor_room_relation WHERE anchor_room_relation.il_id = rooms.il_id AND anchor_room_relation.user_name like CONCAT('%',{0},'%') ) ", keyword));

        wrapper.eq(reqVO.getAuditStatus() != null, RoomsEntity::getAuditStatus, reqVO.getAuditStatus());
        wrapper.eq(reqVO.getOptionStatus() != null, RoomsEntity::getStatus, reqVO.getOptionStatus());
        if (reqVO.getPlaybackStatus() != null) {
            wrapper.eq(RoomsEntity::getPlaybackStatus, reqVO.getPlaybackStatus());
            wrapper.and(e -> e.ne(RoomsEntity::getRecordId, null).or().ne(RoomsEntity::getRecordId, ""));
        }
        wrapper.eq(reqVO.getComplianceCheckStatus() != null, RoomsEntity::getComplianceCheckStatus, reqVO.getComplianceCheckStatus());
        wrapper.eq(reqVO.getLiveRormal() != null, RoomsEntity::getLiveRormal, reqVO.getLiveRormal());
        if (CollectionUtils.isNotEmpty(reqVO.getLiveTypes())) {
            wrapper.in(RoomsEntity::getLiveType, reqVO.getLiveTypes());
        }
        return wrapper;
    }

    private RecordEntity completeById(RecordEntity info, JSONObject field) {
        //1 查看数据是否存在
        RecordEntity recordEntity = new RecordEntity();
        if (info != null && info.getId() > 0) {
            try {
                recordEntity.setId(info.getId());
                recordEntity.setDuration((Integer) field.get(DURATION));
                recordEntity.setStorage((Integer) field.get(STORAGE));
                if (field.containsKey(TRANSCODE_STATUS)) {
                    recordEntity.setTranscodeStatus((Integer) field.get(TRANSCODE_STATUS));
                }
                if (field.containsKey("name")) {
                    recordEntity.setName((String) field.get("name"));
                }
                //更新回放信息
                int result = recordMapper.updateById(recordEntity);
                if (result > 0) {
                    return recordMapper.selectById(info.getId());
                }
            } catch (Exception e) {
                log.info("RecordSqlError", e);
            }
        }
        return null;
    }

    /**
     * 转换成音视频信息的响应
     */
    private UploadRsp convertToUploadRspVo(RecordEntity recordEntity, Map<Integer, String> finalIlIdMap) {
        UploadRsp uploadRsp = new UploadRsp();
        uploadRsp.setId(recordEntity.getId());
        uploadRsp.setAccountId(recordEntity.getAccountId());
        uploadRsp.setDuration(recordEntity.getDuration());
        uploadRsp.setStorage(recordEntity.getStorage());
        uploadRsp.setIlId(recordEntity.getIlId());
        uploadRsp.setSubject(finalIlIdMap.get(recordEntity.getIlId()));
        uploadRsp.setName(recordEntity.getName());
        uploadRsp.setRoomId(recordEntity.getRoomId());
        uploadRsp.setVodId(recordEntity.getVodId());
        uploadRsp.setSource(recordEntity.getSource());
        uploadRsp.setStatus(recordEntity.getStatus());
        uploadRsp.setTranscodeStatus(recordEntity.getTranscodeStatus());
        LocalDateTime createTime = recordEntity.getCreatedAt();
        LocalDateTime updateTime = recordEntity.getUpdatedAt();
        LocalDateTime createdTime = recordEntity.getCreatedTime();
        uploadRsp.setCreatedAt(LocalDateTimeUtil.formatNormal(createTime));
        uploadRsp.setUpdatedAt(LocalDateTimeUtil.formatNormal(updateTime));
        uploadRsp.setCreatedTime(createdTime != null ? LocalDateTimeUtil.formatNormal(createdTime) : null);
        uploadRsp.setDeletedAt(null);
        String downUrl = "";

        String value = redisTemplate.opsForValue().get(RedisKey.RECORD_DOWN_URL + recordEntity.getVodId());
        if (StringUtils.isNotBlank(value)) {
            downUrl = value;
        }
        uploadRsp.setDownUrl(downUrl);
        return uploadRsp;
    }

    /**
     * 转换成回放信息的响应
     * productLiveContentTypeFlag  产品类 标记位;true 表示是产品类；false表示不是产品类
     */
    private RecordRsp convertToRecordRspVo(RecordEntity recordEntity, String recordId, boolean productLiveContentTypeFlag) {
        RecordRsp recordRsp = new RecordRsp();
        BeanUtils.copyProperties(recordEntity,recordRsp);
        recordRsp.setIlId(String.valueOf(recordEntity.getIlId()));
        LocalDateTime createdTime = recordEntity.getCreatedTime();
        long sortDate = recordEntity.getCreatedAt().atZone(ZoneOffset.UTC).toEpochSecond();
        recordRsp.setCreatedTime(createdTime != null ? LocalDateTimeUtil.formatNormal(createdTime) : null);
        recordRsp.setSortDate(sortDate);
        recordRsp.setDuration(secToTime(recordEntity.getDuration()));
        recordRsp.setStorage(calc(recordEntity.getStorage()));
        recordRsp.setIsDefault(recordId.equals(recordEntity.getVodId()) ? 1 : 0);
        recordRsp.setRecordId(recordEntity.getVodId());
        recordRsp.setRecordName(recordEntity.getName());
        recordRsp.setAccountId((long) recordEntity.getAccountId());
        recordRsp.setDocumentExist(0);
        recordRsp.setRoomId(recordEntity.getRoomId());
        recordRsp.setTranscodeStatus(recordEntity.getTranscodeStatus());
        recordRsp.setAuditStatus(recordEntity.getAuditStatus());
        recordRsp.setId(recordEntity.getId());
        String downUrl = "";
        String value = redisTemplate.opsForValue().get(RedisKey.RECORD_DOWN_URL + recordEntity.getVodId());
        if (StringUtils.isNotBlank(value)) {
            downUrl = value;
        }
        recordRsp.setDownUrl(downUrl);
        recordRsp.setAuditStatusSecond(recordEntity.getAuditStatusSecond());
        Integer auditStatusFinal = recordEntity.getAuditStatus();
        if (productLiveContentTypeFlag && auditStatusFinal.equals(RoomAuditStatusEnum.APPROVED.getAuditStatus())) {
            auditStatusFinal = recordEntity.getAuditStatusSecond();
        }
        recordRsp.setAuditStatusFinal(auditStatusFinal);
        return recordRsp;
    }

    /**
     * 字节单位转换,保留的小数位数,默认为2位
     */
    private String calc(long size) {
        if (size <= 0) {
            return "0KB";
        }
        final String[] units = new String[]{"KB", "MB", "GB", "TB", "PB"};
        int digitGroups = (int) (Math.log10(size) / Math.log10(1024));
        return new DecimalFormat("#,##0.0#").format(size / Math.pow(1024, digitGroups)) + units[digitGroups];
    }

    /**
     * 把秒数转换为时分秒的格式
     */
    private String secToTime(int duration) {
        String timeStr;
        int hour;
        int minute;
        int second;
        if (duration <= 0) {
            return ConstStr.TIME_ZERO;
        } else {
            minute = duration / 60;
            if (minute < 60) {
                second = duration % 60;
                timeStr = "00" + ":" + unitFormat(minute) + ":" + unitFormat(second);
            } else {
                hour = minute / 60;
                if (hour > 99) {
                    return "99:59:59";
                }
                minute = minute % 60;
                second = duration - hour * 3600 - minute * 60;
                timeStr = unitFormat(hour) + ":" + unitFormat(minute) + ":" + unitFormat(second);
            }
        }
        return timeStr;

    }

    private String unitFormat(int i) {
        String retStr;
        if (i >= 0 && i < 10) {
            retStr = "0" + i;
        } else {
            retStr = "" + i;
        }
        return retStr;
    }

}
